<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>圆形滑动输入条</title>
		<style>
			body {
				padding: 0;
				margin: 0;
				height: 100vh;
				display: flex;
				justify-content: center;
				align-items: center;
				flex-direction: column;
			}
			.slider {
				height: 100%;
				width: 100%;
				border-radius: 50%;
				box-sizing: border-box;
				position: relative;
				display: flex;
				justify-content: center;
				align-items: center;
				z-index: 10;
			}
			.slider__ball {
				height: 16px;
				width: 16px;
				border-radius: 50%;
				background-color: #64748b;
				position: absolute;
				top: 0;
				left: 0;
				cursor: move;
				user-select: none;
			}
			.container {
				width: 200px;
				height: 200px;
				box-sizing: border-box;
				padding: 8px;
				border-radius: 50%;
				position: relative;
				background-color: #cbd5e1;
				overflow: hidden;
			}
			.overlay {
				border-radius: 50%;
				background: #fff;
				position: absolute;
				top: 16px;
				left: 16px;
				right: 16px;
				bottom: 16px;
				z-index: 5;
			}
			.half {
				position: absolute;
				top: 0;
				left: 0;
				height: 50%;
				width: 100%;
				transform-origin: 50% 100%;
				z-index: 1;
			}
			.half__1 {
				background: #409eff;
			}
			.tick {
				width: 6px;
				height: 6px;
				border-radius: 50%;
				background-color: #fff;
				position: absolute;
				z-index: 8;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<div class="slider">
				<div class="slider__ball"></div>
				<div class="percent"></div>
			</div>
			<div class="overlay"></div>
			<div class="half half__1"></div>
			<div class="half half__2"></div>
		</div>

		<script>
			document.addEventListener("DOMContentLoaded", () => {
				const sliderDOM = document.querySelector('.slider');
				const sliderBallDOM = document.querySelector('.slider__ball');
				const percentDOM = document.querySelector('.percent');
				const halfDOM = document.querySelector(".half__2");

        const { width: sliderWidth } = sliderDOM.getBoundingClientRect();
				const { width: sliderBallWidth } = sliderBallDOM.getBoundingClientRect();
				let dx = 0;
				let dy = 0;
				const radius = sliderWidth / 2;
				const center = radius - sliderBallWidth / 2;
				let totalRadian = 0;
				const step = 10;
				const degreeIncrement = 360 / step;
				const degreesToRadians = Math.PI / 180;

				sliderBallDOM.addEventListener("mousedown", handleMouseDown);

				function handleMouseDown(e) {
					const startPos = {
							x: e.clientX - dx,
							y: e.clientY - dy,
					};
					function handleMouseMove(e) {
						let dxTemp = e.clientX - startPos.x;
						let dyTemp = e.clientY - startPos.y;
						const rawAngleRadians = Math.atan2(dyTemp - center, dxTemp - center);
						const radiansTemp = (rawAngleRadians + Math.PI) / (Math.PI * 2);
						if (radiansTemp * 360 === 360) return;
						const roundedAngleRadians =
							Math.round(
								rawAngleRadians / (degreeIncrement * degreesToRadians)
							) *
							(degreeIncrement * degreesToRadians);
						dx = center + radius * Math.cos(roundedAngleRadians);
						dy = center + radius * Math.sin(roundedAngleRadians);
						const radians = Math.atan2(dy - center, dx - center);
						totalRadian = (radians + Math.PI) / (Math.PI * 2);
						updatePageView();
					};
					function handleMouseUp() {
						document.removeEventListener('mousemove', handleMouseMove);
						document.removeEventListener('mouseup', handleMouseUp);
					};
					document.addEventListener('mousemove', handleMouseMove);
					document.addEventListener('mouseup', handleMouseUp);
				}

				function init(initialRadian = 0) {
					const radians = Math.atan2(0 - center, 0 - center);
					const radian = initialRadian * Math.PI * 2 - Math.PI;
					const dxTemp = center + radius * Math.cos(radian);
					const dyTemp = center + radius * Math.sin(radian);
					dx = dxTemp;
					dy = dyTemp;
					totalRadian = initialRadian;
					updatePageView();
				}
				init();

				function createTicks(step = 0) {
					const container = document.querySelector(".container");
					const angleStep = (2 * Math.PI) / step;
					for (let i = 0; i < step; i++) {
						const tick = document.createElement("div");
						tick.classList.add("tick");
						const angle = angleStep * i;
						const x = center + radius * Math.cos(angle);
						const y = center + radius * Math.sin(angle);
						tick.style.position = "absolute";
						tick.style.left = `${x + 16 - 3}px`;
						tick.style.top = `${y + 16 - 3}px`;
						container.appendChild(tick);
					}
				}
				createTicks(step);

				function updatePageView() {
					sliderBallDOM.style.transform = `translate3d(${dx}px, ${dy}px, 0)`;
					percentDOM.innerText = `${Math.round(totalRadian * 100)}%`;
					halfDOM.style.backgroundColor = totalRadian > 0.5 ? '#409eff' : 'inherit';
					halfDOM.style.transform = `rotate(${totalRadian > 0.5 ? 360 * totalRadian - 180 : 360 * totalRadian}deg)`;
				}
			});
		</script>
	</body>
</html>
